package com.derbysoft.synxisadapter.dswitch3.translator;

import com.derbysoft.dswitch.dto.hotel.common.ChargeItemDTO;
import com.derbysoft.dswitch.dto.hotel.common.RoomRateDTO;
import com.derbysoft.dswitch.dto.hotel.common.TotalDTO;
import com.derbysoft.dswitch.dto.hotel.reservation.HotelReservationRS;
import com.derbysoft.dswitch.dto.hotel.reservation.ReservationRoomStayDTO;
import com.derbysoft.dswitch.remote.hotel.dto.HotelReservationRequest;
import com.derbysoft.dswitch.remote.hotel.dto.HotelReservationResponse;
import com.derbysoft.synxisadapter.commons.dto.synxis.HotelReservation;
import com.derbysoft.synxisadapter.commons.dto.synxis.OTAHotelResRS;
import com.derbysoft.synxisadapter.commons.exception.HotelConfirmNoNotFoundException;
import com.derbysoft.synxisadapter.commons.model.Channel;
import com.derbysoft.synxisadapter.dswitch2.translator.Translator;
import com.derbysoft.synxisadapter.dswitch2.translator.impl.TranslateHelper;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * User: jason
 * Date: 2012-11-23
 */
@Component("ds3HotelResRSTranslator")
public class HotelResRSTranslator extends AbstractTranslator
        implements Translator<List<OTAHotelResRS>, HotelReservationResponse, HotelReservationRequest> {

    private static final String SPLIT = ";";

    @Override
    public HotelReservationResponse translate(List<OTAHotelResRS> otaHotelResRSes, HotelReservationRequest request) {
        HotelReservationResponse response = new HotelReservationResponse();
        response.setTaskId(request.getHeader().getTaskId());
        response.setHotelReservationRS(createReservationRS(otaHotelResRSes, request));
        return response;
    }

    private HotelReservationRS createReservationRS(List<OTAHotelResRS> otaHotelResRSes, HotelReservationRequest request) {
        HotelReservationRS hotelReservationRS = new HotelReservationRS();
        Channel channel = loadChannel(request.getHeader().getSource());
        hotelReservationRS.setErsp(request.getHotelReservationRQ().getErsp());
        hotelReservationRS.setHotelReservation(request.getHotelReservationRQ().getHotelReservation());
        ReservationRoomStayDTO reservationRoomStayDTO = hotelReservationRS.getHotelReservation().getRoomStaysList().get(0);
        reservationRoomStayDTO.setHotelReservationNo(translateReservationNo(otaHotelResRSes));
        reservationRoomStayDTO.setRoomRate(translateRoomRate(otaHotelResRSes, channel));
        reservationRoomStayDTO.setTotal(translateTotal(channel, otaHotelResRSes));
        return hotelReservationRS;
    }

    private RoomRateDTO translateRoomRate(List<OTAHotelResRS> otaHotelResRSes, Channel channel) {
        HotelReservation hotelReservation = otaHotelResRSes.get(0).getHotelReservations().getHotelReservation().get(0);
        return createDS3RoomRate(hotelReservation.getRoomStays().getRoomStay().get(0).getRoomRates().getRoomRate().get(0).getRates(), channel);
    }

    private TotalDTO translateTotal(Channel channel, List<OTAHotelResRS> otaHotelResRSes) {
        BigDecimal amountBeforeTax = BigDecimal.ZERO;
        BigDecimal amountAfterTax = BigDecimal.ZERO;

        HotelReservation hotelReservation = otaHotelResRSes.get(0).getHotelReservations().getHotelReservation().get(0);
        amountBeforeTax = amountBeforeTax.add(hotelReservation.getResGlobalInfo().getTotal().getAmountBeforeTax());
        amountAfterTax = amountAfterTax.add(hotelReservation.getResGlobalInfo().getTotal().getAmountAfterTax());
        String currencyCode = hotelReservation.getResGlobalInfo().getTotal().getCurrencyCode();

        TotalDTO totalDTO = new TotalDTO();
        if (channel.isInclusiveTaxRate()) {
            totalDTO.setAmountAfterTax(amountAfterTax.doubleValue());
        } else {
            totalDTO.setAmountBeforeTax(amountBeforeTax.doubleValue());
        }
        totalDTO.setTaxesList(calcTax(amountBeforeTax, amountAfterTax));
        totalDTO.setCurrency(currencyCode);
        return totalDTO;
    }

    private List<ChargeItemDTO> calcTax(BigDecimal amountBeforeTax, BigDecimal amountAfterTax) {
        ArrayList<ChargeItemDTO> taxes = new ArrayList<ChargeItemDTO>();
        ChargeItemDTO tax = new ChargeItemDTO();
        tax.setValue(TranslateHelper.setScale(amountAfterTax.subtract(amountBeforeTax)).doubleValue());
        tax.setType(ChargeItemDTO.ChargeType.FIXED);
        taxes.add(tax);
        return taxes;
    }

    private String translateReservationNo(List<OTAHotelResRS> otaHotelResRSes) {
        StringBuilder builder = new StringBuilder();
        for (OTAHotelResRS otaHotelResRS : otaHotelResRSes) {
            HotelReservation hotelReservation = otaHotelResRS.getHotelReservations().getHotelReservation().get(0);
            builder.append(hotelReservation.getUniqueID().getID()).append(SPLIT);
        }
        String confirmNos = builder.toString();
        if (StringUtils.isBlank(confirmNos)) {
            throw new HotelConfirmNoNotFoundException();
        }
        return StringUtils.removeEnd(confirmNos, SPLIT);
    }
}
